/*
 * TacticaJuan.java
 *
 * Created on 17 de julio de 2006, 15:06
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package futbol.tacticas.concursantes2007.KalimeroFC;

import java.awt.Point;
import java.awt.Color;
import java.util.Vector;


import futbol.tacticas.*;
import futbol.tacticas.concursantes.Tactica;
import futbol.tacticas.concursantes2007.KalimeroFC.Jugador;
import futbol.tacticas.concursantes2007.KalimeroFC.TipoJugador;
import futbol.tacticas.concursantes2007.KalimeroFC.Zona;
import futbol.General;
/**
 *
 * @author Administrador
 */
public class TacticaKalimero implements Tactica{
    	
	private final int PASE_ADELANTE =5;
	private final int FUERZA_DISTANCIA = 15;
	
    private Vector<Jugador>equipo = new Vector<Jugador>(11);
    private Point[] trayectoriaBola = {new Point(0,0),new Point(1,0),new Point(2,0)};
    private int contador;
    private int contadorBola;
    private double mediaContrarios=0;
    private final double conversor = 180/Math.PI;
    
    public TacticaKalimero(){
    	equipo.add(new Jugador(0,7,new Zona(-150,0,50),TipoJugador.Portero));
    	equipo.add(new Jugador(1,6,new Zona(-120,0,50),TipoJugador.Defensa));
    	equipo.add(new Jugador(2,5,new Zona(-110,-40,50),TipoJugador.Defensa));
    	equipo.add(new Jugador(3,5,new Zona(-110,40,50),TipoJugador.Defensa));
    	equipo.add(new Jugador(4,4,new Zona(-90,85,60),TipoJugador.Lateral)); //J 5
    	equipo.add(new Jugador(5,4,new Zona(-90,-85,60),TipoJugador.Lateral)); // J 6
    	equipo.add(new Jugador(6,6,new Zona(-70,0,40),TipoJugador.Centro));  //J7
    	equipo.add(new Jugador(7,6,new Zona(0,-40,50),TipoJugador.MediaPunta)); // J 8
    	equipo.add(new Jugador(8,6,new Zona(-10,0,40),TipoJugador.Centro)); // J9
    	equipo.add(new Jugador(9,7,new Zona(50,0,40),TipoJugador.Delantero)); //j10
    	equipo.add(new Jugador(10,6,new Zona(0,40,50),TipoJugador.MediaPunta)); //J11
    }

    
    public Color getColor1() {
        return Color.white;
    }

    public Color getColor2() {
        return Color.yellow;
    }

    public Color getColorNumero() {
        return Color.black;
    }

    public String getNombre() {
        return "Kalimero F.C.";
    }

    public int getXInicial(int n) {
        return equipo.get(n).getXInicial();
    }

    public int getYInicial(int n) {
        return equipo.get(n).getYInicial();
    }

    public int getFuerza(int n) {
        return equipo.get(n).getFuerza();
    }

    public Vector<Comando> getComandos(SituacionJugadores sj) {
    	double media = 0;
    	contador++;
    	trayectoriaBola[contadorBola] = sj.getBola();
    	contadorBola++;
    	if(contadorBola >2){
    		contadorBola=0;
    	}
    	
        Vector<Comando> com=new Vector<Comando>();
        Point bola = sj.getBola();
        Point[] jugadores = sj.getMisJugadores();
        Point[] contrarios = sj.getContrario();
        
        // Jugadores por zona
        Zona zona = null;
        Jugador jugador = null;
        
        for(int i=0;i<11;i++){
        	jugador = equipo.get(i);
        	zona = jugador.getZona();
        	jugador.limpia();
        	for(int n=0;n<11;n++){
            	zona.addJugador(n, jugadores[n]);
            	zona.addContrario(n, contrarios[n]);
            	jugador.addContrario(contrarios[n]);
            }
        	zona.addBola(sj.getBola());
        	if(contador%5 == 1 && i!= 0){
        		zona.modificaRadio(mediaContrarios,contador);
        	}
        	if(i!=0){
        		media = media + zona.getMediaContrarios(contador);
        	}
        	//System.out.println("Media zona " + i + " = " + zona.getMediaContrarios(contador) +" Radio " + zona.getRadio() );
        }
        //System.out.println("Zona total " + mediaContrarios);
        mediaContrarios = media /10.;
        
        // comando para cada jugador
        for(int numero=0;numero<11;numero++){
        	Jugador j = equipo.get(numero);
        	Point pj = jugadores[numero];
        	zona = j.getZona();
        	// Muevo las zonas con la bola

       		int modificadorX = 0;
       		int modificadorY = 0;
       		
    		switch(j.getTipo()){
    			case Portero:   	
    				
    				if(zona.estaBola()){
    					if(!clasificaZonaPase(com,numero,sj,-Math.PI/2,Math.PI/2)){
    						com.add(new ComandoTiroAPuerta(numero, puntoDeDisparo(pj, contrarios)));
        				}
    	    			com.add(new ComandoIrA(numero,sj.getBola().getX(),sj.getBola().getY()));
    	    		}else{
    	    			if(pj.x > -100){
        					com.add(new ComandoIrA(numero,-101,pj.y));
        				}else{
        					com.add(new ComandoIrA(numero,zona.getCentroModificadoX(),zona.getCentroModificadoY()));
        				}
    	    		}    	
    				break;
    			case Defensa:
    				
    				if(sj.getBola().x > 0 && sj.getBola().x < 100 ){
    					modificadorX = sj.getBola().x;
    	    		}if(sj.getBola().x>=120){
    	    			modificadorX = 120;
    	    		}
    	    			
    				zona.setModificador(new Point(modificadorX,modificadorY));		
    				if(zona.estaBola()){
    					if(!clasificaZonaPase(com,numero,sj,-90 * conversor,90 * conversor)){
    						com.add(new ComandoTiroAPuerta(numero, puntoDeDisparo(pj, contrarios)));
        				}
    	    			com.add(new ComandoIrA(numero,sj.getBola().getX(),sj.getBola().getY()));
    	    		}else{
    	    			com.add(new ComandoIrA(numero,zona.getCentroModificadoX(),zona.getCentroModificadoY()));
    	    		}    	
    				break;
    			case Libero:
    				if(sj.getBola().x > 0){
    	    			zona.setModificador(new Point(sj.getBola().x,(int)(sj.getBola().getY()/120.) * zona.getRadio()/2));
    	    		}else{
    	    			zona.setModificador(new Point(modificadorX,modificadorY));
    	    		}
    				
    				if(zona.estaBola()){
    					if(!clasificaZonaPase(com,numero,sj, -90 * conversor ,90 * conversor)){
    						com.add(new ComandoTiroAPuerta(numero, puntoDeDisparo(pj, contrarios)));
        				}
    	    			com.add(new ComandoIrA(numero,sj.getBola().getX(),sj.getBola().getY()));
    	    		}else{
    	    			com.add(new ComandoIrA(numero,zona.getCentroModificadoX(),zona.getCentroModificadoY()));
    	    		}    	
    				break;
    			case Lateral:
    				
    				if( bola.x > -60){
    					modificadorX = bola.x +60;
    					if(zona.getCentroX() + modificadorX > 130 ){
    						modificadorX = 130 - zona.getCentroX();
    						modificadorY = (int)(Math.signum(zona.getCentroY())) * (-20);
    					}
    				}

    				zona.setModificador(new Point(modificadorX,modificadorY));
    				
    				if(zona.estaBola()){
    					if(bola.x>130){
    						if(!clasificaZonaPase(com,numero,sj,Math.toRadians(-90),Math.toRadians(90))){
    							com.add(new ComandoTiroAPuerta(numero, puntoDeDisparo(pj, contrarios)));
    						}
        				}else{
    	     				if(!avanceConPelota(com,numero,sj,zona,j.getVelocidad())){
    	     				  if(!clasificaZonaPase(com,numero,sj,Math.toRadians(-90),Math.toRadians(90))){
    	     					 com.add(new ComandoTiroAPuerta(numero, puntoDeDisparo(pj, contrarios)));
    	     				  }
    	     				}
        				}
    	    			com.add(new ComandoIrA(numero,sj.getBola().getX(),sj.getBola().getY()));
    	    		}else{
    	    			com.add(new ComandoIrA(numero,zona.getCentroModificadoX(),zona.getCentroModificadoY()));
    	    		}
    				break;
    			case Centro:
    				
    				if(sj.getBola().x >=80){
    					modificadorY = (int)(sj.getBola().getY()/2.);
    					modificadorX=bola.x;
    	    		}else if (bola.x<=80 && bola.x> -40 ){
    	    			modificadorY = (int)(sj.getBola().getY()/4.);
    	    			modificadorX= bola.x;
    	    		}else{
    	    			modificadorY = (int)(sj.getBola().getY()/2.);
    	    		}
    				zona.setModificador(new Point(modificadorX,modificadorY));
    				
    				if(pj.x>130){
     					com.add(new ComandoTiroAPuerta(numero,0));
     				}
    				if(zona.estaBola() || sj.getMasCercanoDeBola()==numero){
    					if(!avanceConPelota(com,numero,sj,zona,j.getVelocidad())){
        				if(!clasificaZonaPase(com,numero,sj,Math.toRadians(-90),Math.toRadians(90))){
        					com.add(new ComandoTiroAPuerta(numero, puntoDeDisparo(pj, contrarios)));
        					}
        				}
    	    			com.add(new ComandoIrA(numero,sj.getBola().getX(),sj.getBola().getY()));
    	    		}else{
    	    			com.add(new ComandoIrA(numero,zona.getCentroModificadoX(),zona.getCentroModificadoY()));
    	    		}    	
    				break;
    			case MediaPunta:
    				if(sj.getBola().x > -50 && sj.getBola().x <100){
    	    			zona.setModificador(new Point(sj.getBola().x + 50,0));
    	    		}else if(sj.getBola().x>=110){
    	    			zona.setModificador(new Point(sj.getBola().x,(int)(sj.getBola().getY()/120.) * zona.getRadio() ));
    	    		}else{
    	    			zona.setModificador(new Point(0,0));
    	    		}
    				
    				
    				
    				if( zona.estaBola() || sj.getMasCercanoDeBola() == numero ){
    					if(sj.getBola().x > 130 || !avanceConPelota(com,numero,sj,zona,j.getVelocidad()) || !clasificaZonaPase(com,numero,sj,-90 * conversor,90*conversor)){
    						com.add(new ComandoTiroAPuerta(numero, puntoDeDisparo(pj, contrarios)));
        				}
    	    			com.add(new ComandoIrA(numero,sj.getBola().getX(),sj.getBola().getY()));
    	    		}else{
    	    			com.add(new ComandoIrA(numero,zona.getCentroModificadoX(),zona.getCentroModificadoY()));
    	    		}    	
    				break;
    			case Delantero:
    				if(sj.getBola().x > - 50 && sj.getBola().x < 0){
    						modificadorX = sj.getBola().x + 50;
    						modificadorY = 0;
    						
    				}else if(sj.getBola().x >= 0 && sj.getBola().x <110){
    					
    						modificadorX = sj.getBola().x;
    						modificadorY = 0;
    						
    	    		}else if(sj.getBola().x >=110 ){
    	    				modificadorX = 85;
    	    				modificadorY = (int)(sj.getBola().getY()/2.);
    	    		}else{
    	    			zona.setModificador(new Point(0,0));
    	    		}
    				zona.setModificador(new Point(modificadorX,modificadorY));
    				if(zona.estaBola()|| sj.getMasCercanoDeBola() == numero){
    	    			com.add(new ComandoIrA(numero,sj.getBola().getX(),sj.getBola().getY()));
    	    		}else{
    	    			com.add(new ComandoIrA(numero,zona.getCentroModificadoX(),zona.getCentroModificadoY()));
    	    		}
    				com.add(new ComandoTiroAPuerta(numero, puntoDeDisparo(pj, contrarios)));
    				break;
    		}

        }        
        
        return com;
    }
    
    // Devuelve la mejor zona a pasar
    private boolean clasificaZonaPase(Vector<Comando> com,int jugador,SituacionJugadores sj, double minAngulo, double maxAngulo){
    	Point pos = sj.getBola();
		Zona zona = null;
		int nmax = 0;
		Point jt;
		double maxPuntos =-5;
		double puntos = 0;
		double orixenX = pos.getX();
		double orixenY = pos.getY();
		double destinoX = 0;
		double destinoY= 0;
//		System.out.println(">>>>>> JUGADOR " + (jugador + 1) + " <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" );
		for (int n = 1; n < 11; n++) {
			if (n != jugador) {
				jt = sj.getMisJugadores()[n];
				zona = equipo.get(n).getZona();

//				double destinoX = jt.getX();
//				double destinoY = jt.getY();
				double destinoXTemp = zona.getCentroModificadoX();
				double destinoYTemp = zona.getCentroModificadoX();
				
				Double angulo = General.getAngulo(orixenX,orixenY,destinoXTemp,destinoYTemp);
				angulo = angulo > Math.PI?angulo-(2. * Math.PI):angulo;
				
				Double distancia = General.getDistancia(orixenX,orixenY, destinoXTemp,destinoYTemp);
				
//				System.out.println("Zona  " + (n+1) );
//				System.out.println( "Pase Maximo: " + equipo.get(jugador).getPaseMaximo() );
//				System.out.println( "Distancia: " + distancia +" Puntos "+  ((double)distancia / equipo.get(jugador).getPaseMaximo()));
//				System.out.println( "Angulo Pase: " +   angulo + " Puntos "+(1. - (Math.pow(angulo, 4.)/ ( Math.pow(Math.PI,4.)))));
//				System.out.println( "Contrarios: " + equipo.get(jugador).getContrarios() + " Puntos " + (1 - ((double)equipo.get(jugador).getContrarios()/2.)));
//				System.out.println( "jugadores en pase: " + pasilloPase(new Point((int)orixenX,(int)orixenY), new Point((int)destinoXTemp,(int)destinoYTemp),sj.getContrario()));
				
				if (distancia > equipo.get(jugador).getPaseMaximo() 
						||  angulo < minAngulo || angulo > maxAngulo) {
//					 System.out.println(" ***** ZONA " + n + "demasiado lejana para jugador " + jugador + "minAngulo " +minAngulo + " - " + maxAngulo);
				} else {
//					if (zona.getCentroModificadoX() > sj.getBola().x) {
//						puntos = puntos + pesoX;
//					}
					//puntos = puntos + (2 - equipo.get(jugador).getContrarios());
					
					puntos = Math.random() - pasilloPase(new Point((int)orixenX,(int)orixenY), new Point((int)destinoX,(int)destinoY),sj.getContrario());
					
//					puntos = ( (double)distancia / equipo.get(jugador).getPaseMaximo()) 
//							+ (1. - (angulo * angulo / ( Math.PI * Math.PI))
//							+ ( (double)zona.diferenciaDeJugadores() / 2.));
//							//+  (1 - ((double)equipo.get(jugador).getContrarios()/2.))); 
//					System.out.println("Jugador:"+jugador+" puntos para pasar a " + (n +1) + " son " + puntos);
					
					if (puntos > maxPuntos) {
						nmax = n;
						maxPuntos = puntos;
						destinoX = destinoYTemp;
						destinoY = destinoYTemp;
					}
				}
			}
		}

//		System.out.println(" Mejor zona pase para jugador " + (jugador+1) +" es " + (nmax + 1)  + " se pasa de ("+ orixenX+"," + orixenY +") a (" + destinoX+  ","+ destinoY +")");
		boolean res = (nmax != 0);
		if (res) {
//			com.add(new ComandoPase(jugador,nmax));

			com.add(new ComandoGolpearBola(jugador, destinoX,destinoY));
		}
		return res;
    }
    
    private boolean avanceConPelota(Vector<Comando> com,int jugador,SituacionJugadores sj,Zona zona,int velocidad){
    	Point j = sj.getMisJugadores()[jugador];
    	Point bola = sj.getBola();
    	double d = zona.getCentroModificadoY() - j.getY();
    	double x =0; 
    	double y= 0;
    	double paso = PASE_ADELANTE * velocidad;
    	//System.out.println("d=" + d + " = "+  zona.getCentroY() +"-"+j.getY());
    	if(Math.abs(d) > paso){
    		x = j.getX() + paso * Math.cos(Math.PI/4.);
    		y = j.getY() + (d/Math.abs(d)) * paso * Math.sin(Math.PI/4.);	
    	}else{
    		y = zona.getCentroY();
    		x = j.getX() + Math.sqrt( (paso * paso) - (d * d) );
    	}
    	Point[] contrarios = sj.getContrario();
    	boolean flag = true;
    	for(int i=1;i<11;i++){
    		if(General.getDistancia(x, y, contrarios[i].getX(),contrarios[i].getY())< ((double)(50. / velocidad))){
    			flag = false;
    			break;
    			//System.out.println("Hay un jugador en la zona de pase ");
    		}
    		else if( Math.abs(contrarios[i].getX() - j.getX()) <= 10*(6-velocidad) ){
    			flag = false;
    			break;
    		}
    		
    	}
    	if(flag){
    		com.add(new ComandoGolpearBola(jugador,x,y));
    		//System.out.println(jugador + " Golpeamos a " + x + "," + y);
    	}
    	else{
    		if(Math.random()>0.8){
    			//com.add(new ComandoGolpearBola(jugador,bola.x, bola.y));
    			com.add(new ComandoGolpearBola(jugador,bola.x, bola.y + 10.));
    			flag = true;
    		}
    	}
    	return flag;
    }
    
    
    /**
     * 
     * @param j
     * @param contrarios
     * @return
     */
    private int puntoDeDisparo(Point j, Point[] contrarios){
    	int max = 12;
    	int temp;
    	Point punto = null;
    	for(int i=1;i<60;i++){
    		punto = new Point(170, 30 - i);
    		temp = pasilloPase(j,punto,contrarios);
    		if(temp < max){
    			max = temp;
    		}
    	} 	
    	return max;
    }

    
    private int pasilloPase(Point orixen,Point fin,Point[] contrarios){
    	
    	double a=(fin.getY() - orixen.getY())/(fin.getX() - orixen.getX());
    	double b=1;
    	double c= orixen.getY() - a * orixen.getX() ;
    	int contador=0;
    	for(int i=0;i<contrarios.length;i++){
    		Point p = contrarios[i];
    		
    		 if(p.x < (orixen.x>fin.x?orixen.x:fin.x)
				&& p.x > (orixen.x>fin.x?fin.x:orixen.x)
				&& p.y < (orixen.y>fin.y?orixen.y:fin.y)
				&& p.y < (orixen.y>fin.y?fin.y:orixen.y)){
    			// System.out.println("Distancia del jugador " + (i+1) + ": "+ distanciaRectaPunto(a,b,c,p));
	    		if(distanciaRectaPunto(a,b,c,p)< 20.){
	    			contador++;
	    		}
    		 }
    	}
    	return contador;
    }
    
    private double distanciaRectaPunto(double a,double b,double c,Point punto){
    	double modulo = Math.sqrt(Math.hypot(a, b));
    	if(modulo != 0){
    		return Math.abs(a*punto.getX() + b * punto.getY() + c) / modulo;
    	}else{
    		return c;
    	}
    }
    
    
    
    
    
    
    
    
    
    
    
    
}
